import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.PriorityBlockingQueue;

import CommonClass.*;
import WebSearch.*;


public class Search_engine implements Runnable {

	private int num_found;
	private boolean finished; //finished searching status
	private String search_term;
	private int num_threads;
	private static final int max_num_thread=10;
	private PriorityBlockingQueue<Integer> running_threads;
	private PriorityBlockingQueue <Integer> available_threads;
	private Thread [] search_thread;
	private boolean running;
	private String search_result;
	private Thread main_thread;
	private String base_website;
	private static final int timeout= 30; //30s timeout
	private Timer timer;
	private Thread timer_thread;
	private Database database;

	@Override
	public void run() {

		// TODO Auto-generated method stub
		database.add_url(base_website);
		System.out.println(base_website);
		try {



			while(database.get_num_result()<10)
			{
				if(available_threads.size()>0&&database.get_num_unprocessed_url()>0)
				{
					String url= database.get_unprocessed_url();
					int id= available_threads.poll();
					System.out.println(url);
					running_threads.add(id);
					Search_thread_code search_thread_code = new Search_thread_code(id, this, url, database,search_term);
					search_thread[id]= new Thread(search_thread_code);
					search_thread[id].start();

				}


				Thread.sleep(1);
			}


		} catch (InterruptedException e) {
			// TODO Auto-generated catch block


		} catch (Exception e) {
			// TODO Auto-generated catch block


			e.printStackTrace();
		}

		//wait all thread to stop
		for (Thread thread : search_thread) {
			try {
				thread.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	

		timer_thread.interrupt();

		update_result();

		running=false;
		finished=true;

	}


	private void update_result()
	{
		num_found=database.get_num_result();


		display_result();
	}


	private void display_result()
	{
		TreeMap<String, IMG> result= database.get_image_result();
		search_result="";
		for(Map.Entry<String,IMG> entry : result.entrySet()) {
			String template="<br><a href=\"$image_result\"><img src=\"$image_result\" ></a></br>";
			
			search_result+=template.replace("$image_result", entry.getKey());

		}
	}

	public synchronized void update_thread_finished(int id)
	{
		running_threads.remove(id);
		available_threads.add(id);
	}
	public Search_engine() {
		// TODO Auto-generated constructor stub
		num_found=0;
		finished=false;
		num_threads=0;
		running=false;
		search_term="";
		search_result="";




	}


	private boolean check_url_database_and_check_keyword() //todo function
	{
		return false;
	}

	private void restart()
	{
		num_found=0;
		finished=false;
		num_threads=0;
		running=false;

		search_thread= new Thread[max_num_thread];
		running_threads= new PriorityBlockingQueue<Integer>();
		available_threads=new PriorityBlockingQueue<Integer>();
		for(int i=0; i<max_num_thread; i++)
		{
			available_threads.add(i);
			search_thread[i]= new Thread();
		}
		database= new Database();

	}

	public String get_search_result()
	{
		return search_result;
	}
	public String get_search_term()
	{
		return search_term;
	}
	public String get_website_search()
	{
		return base_website;
	}
	public int get_num_found()
	{
		return num_found;
	}

	public boolean is_finished()
	{
		return finished;
	}



	public void set_search_term(String search_term, String base_website)
	{
		if(!this.search_term.equals(search_term)||!this.base_website.equals(base_website))
		{

			this.search_term=search_term;
			this.base_website=base_website;
			if(!check_url_database_and_check_keyword())
			{
				if(running)
				{
					main_thread.interrupt();
					timer_thread.interrupt();
					try {
						main_thread.join();
						timer_thread.join();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}


				restart();
				timer= new Timer(timeout,this);
				timer_thread=new Thread(timer);
				main_thread= new Thread(this);
				running=true;
				main_thread.start();
				timer_thread.start();
			}
		}




	}
	public boolean is_running()
	{
		return running;
	}
	public void stop()
	{
		main_thread.interrupt();
		try {
			main_thread.join();

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


}
